<script setup lang="ts">
import {computed, ref, onMounted} from 'vue'
import {OptionItem} from "@/components/SelectWithPage/type.ts";
import type {PropType as VuePropType} from "@vue/runtime-core";

// ======================================================【属性】开始=====================================================
const props = defineProps({
  defaultValue: {type: [String, Number, Array, Boolean, Object], default: null},
  multiple: {type: Boolean, default: false},
  remoteValue: {type: Boolean, default: false},
  remoteMethod: {type: Function, default: () => null},
  optionSource: {type: Array as VuePropType<OptionItem[]>, default: () => []},
  loading: {type: Boolean, default: false},
  paginationOption:{
    type: Object,
    default: () => {
      return {
        pageSize: 10, // 每页显示条数
        currentPage: 1, // 当前页
        pagerCount: 10, // 按钮数，超过时会折叠
        total: 0 // 总条数
      }
    }
  }
});
// ======================================================【属性】结束=====================================================

// ======================================================【事件】开始=====================================================
const emits = defineEmits(['handleInput', 'change', 'clearValidate', 'visibleChange', 'sizeChange', 'currentChange','clear'])
// ======================================================【事件】结束=====================================================

// ======================================================【变量】========================================================
// 选中的值
const selectedOption = ref(null)
// 存储所有选项数据
const options = ref<OptionItem[]>([])
// 过滤的关键词
const filterKeyword = ref("");
// 数据总量，用于分页
const optionTotal = ref(0);
// 分页
const pagination = ref({
  currentPage: props.paginationOption.currentPage,
  pageSize: props.paginationOption.pageSize,
  total: props.paginationOption.total,
  pageSizes: [10, 20, 50, 100]
});
// ======================================================【方法】========================================================
/**
 * 处理输入事件，更新 selectedOption
 */
const handleInput = (value: string) => {
  selectedOption.value = value;
  console.log("处理输入事件")
  emits("handleInput", value);
}

/**
 * 处理每页显示数量变化事件
 */
const handleSizeChange = (newSize: number) => {
  pagination.value.pageSize = newSize;
  // 当每页数量改变时，重置当前页为第一页
  pagination.value.currentPage = 1;
  // 可能需要重新获取当前页的数据
  emits("sizeChange", newSize)
  console.log("处理每页显示数量变化事件")
}
/**
 * 处理下拉菜单的可见性变化
 * 加载选择框组件的时候并不需要加载数据，只需在下拉加载框显示时加载当前页的数据
 */
const handleVisibleChange = (visible: boolean) => {
  pagination.value.currentPage = 1;
  // 可能需要重新获取当前页的数据
  emits("visibleChange", visible);
  console.log("处理下拉菜单的可见性变化")
}

/**
 * 翻页改变方法
 */
const handleCurrentChange = (newPage: number) => {
  pagination.value.currentPage = newPage;
  emits("currentChange", newPage);
  console.log("翻页改变方法")
}

/**
 * 选中值发生变化时触发
 */
const handleChange = (selectVal: any) => {
  emits('change', selectVal);
  console.log("选中值发生变化时触发")
}

/**
 * 处理清除事件
 */
const handleClear = () => {
  selectedOption.value = [];// 清空已选值
  emits("clear")
  console.log("处理清除事件")
}

/**
 * 自定义过滤方法
 * @param query 输入框中的值
 */
const handleFilterOption = (query: string) => {
  console.log("可以利用筛选功能快速查找选项")
  filterKeyword.value = query && query.trim();
  pagination.value.currentPage = 1;
}

const handleRemoteMethod = (query: string) => {
  console.log("输入关键字以从远程服务器中查找数据")
  props.remoteMethod(
      filterKeyword.value,
      pagination.value.currentPage,
      pagination.value.pageSize
  ).then((res: any) => {
    optionTotal.value = res.length;
    options.value = res?.map((val:OptionItem) => ({
      label: `${val.label}`,
      value: val.value
    }))
  });
}

// ======================================================【计算属性】=====================================================
/**
 * 根据当前页码和每页显示数量计算并返回当前页的选项
 */
const paginatedOptions = computed(() => {
  const start = (currentPage.value - 1) * pageSize.value;
  const end = start + pageSize.value;

  if (props.remoteValue) { // 从服务器远程加载

  }
  if (filterKeyword.value) {
    let optionList = options.value.filter((option) => {
      return option.label.indexOf(filterKeyword.value) > -1 || option.label.toUpperCase().indexOf(filterKeyword.value.toUpperCase()) > -1;
    });
    optionTotal.value = optionList.length;
    return optionList.slice(start, end);
  } else {
    optionTotal.value = options.value.length;
    return options.value.slice(start, end);
  }
});

// ======================================================【初始化】=======================================================
onMounted(() => {
  options.value = props.optionSource;
})
</script>

<template>
  <el-select
      v-model.trim="selectedOption"
      placeholder="请选择……"
      clearable
      filterable
      :filter-method="handleFilterOption"
      :multiple="props.multiple"
      @change="handleChange"
  >
    <el-option v-for="option in paginatedOptions" :key="option.value" :label="option.label" :value="option.value"/>

    <!-- 下拉列表底部的内容 -->
    <template #footer>
      <el-pagination
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :current-page="currentPage"
          :page-sizes="[10, 20, 30, 40]"
          :page-size="pageSize"
          layout="total, prev, pager, next, jumper"
          :total="optionTotal"
      />
    </template>

    <template #loading>
      <div v-loading="loading" element-loading-text="加载中" class="h-20"></div>
    </template>
  </el-select>
</template>

<style lang="css" scoped>
.select-pagination {
  margin-top: 10px;
}
</style>